Jdbc 테스트에서 NoSuchBeanDefinitionException 해결
What is Problem
RacingCarDAOTest에서 필드로 carDAO를 갖고, 구현체 RacingCarDAO를 필드 주입을 통해 주입하려는 상황
RacingCarDAO
@Repository
public class RacingCarDAO implements CarDAO {
private final JdbcTemplate jdbcTemplate;
...
}
이렇게 @Repository 어노테이션을 붙여놓음으로써 빈 등록을 하였다.
그리고 RacingCarDAOTest에서는 다음과 같이 사용하려고 한다.
@JdbcTest
@Sql(scripts = {"classpath:data.sql"})
class RacingCarDAOTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private RacingCarDAO racingCarDAO;
하지만 아래와 같은 에러가 발생한다.
Error creating bean with name 'racingcar.database.RacingCarDAOTest': Unsatisfied dependency expressed through field 'racingCarDAO'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'racingcar.car.repository.RacingCarDAO' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
RacingCarDAO가 빈 등록이 되어있지 않는다는 상황
Why it happnes
@JdbcTest는 모든 컴포넌트를 스캔하지 않고 테스트와 관련된 컴포넌트들만 스캔한다.
Using this annotation will disable full auto-configuration and instead apply only configuration relevant to JDBC tests. docs.spring.io
그래서 @Repositoy 어노테이션을 붙인 RacingCarDAO는 스캔되지 않는다.
How to solve
-
@JdbcTest클래스에@Import(RacingCarDAO.class)추가하기 가장 간단한 방법으로 빈 추가가 가능하다.@Import는 주로 Configure 컴포넌트를 불러오는 방법으로 사용된다고 하지만, 위의 예시처럼 한 개의 컴포넌트를 추가하는 것도 가능하다. -
Configure 컴포넌트를 만들어서 불러오기 아래와 같이 TestConfiguration 컴포넌트를 만들어
@Import(TestConfiguration.class)를 붙이는 방식으로 사용 가능하다.
@Configuration
public class TestConfiguration {
@Autowired
JdbcTemplate jdbcTemplate;
@Bean
public CarDAO carDAO() {
return new RacingCarDAO(this.jdbcTemplate);
}
}
Additional
@JdbcTest는 transactional하고, in-memory database를 사용한다.
즉, 각 테스트가 끝날때마다 roll back 시키고, 실제 데이터베이스에 저장되진 않는다.